<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>知识库管理 - RAG 系统</title>
    <script src="static/js/tailwindcss.js"></script>
    <link rel="icon" type="image/svg+xml" href="static/favicon.svg">
    <link href="static/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#3B82F6',
                        secondary: '#6366F1',
                        neutral: '#F3F4F6',
                        dark: '#1F2937'
                    },
                    fontFamily: {
                        sans: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .scrollbar-hide {
                -ms-overflow-style: none;
                scrollbar-width: none;
            }
            .scrollbar-hide::-webkit-scrollbar {
                display: none;
            }
        }
    </style>
</head>
<body class="bg-gray-50 font-sans">
    <div class="min-h-screen flex flex-col">
        <!-- 顶部导航 -->
        <header class="bg-white border-b border-gray-200 p-4">
            <div class="max-w-7xl mx-auto flex items-center justify-between">
                <div class="flex items-center">
                    <a href="/" class="text-primary hover:text-primary/80 mr-6 flex items-center">
                        <i class="fa fa-arrow-left mr-1"></i> 返回聊天
                    </a>
                    <h1 class="text-xl font-bold text-gray-800">知识库管理</h1>
                </div>
                <div>
                    <button id="add-knowledge-btn" class="bg-primary hover:bg-primary/90 text-white py-2 px-4 rounded-md flex items-center transition-colors">
                        <i class="fa fa-plus mr-2"></i> 添加知识
                    </button>
                </div>
            </div>
        </header>
        
        <!-- 主内容区 -->
        <main class="flex-1 max-w-7xl w-full mx-auto p-4 sm:p-6 lg:p-8">
            <!-- 搜索和筛选 -->
            <div class="bg-white rounded-lg shadow-sm p-4 mb-6">
                <div class="flex flex-col sm:flex-row gap-4">
                    <div class="flex-1">
                        <div class="relative">
                            <input 
                                type="text" 
                                id="search-input" 
                                placeholder="搜索知识库内容..." 
                                class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary focus:border-primary transition-all"
                            >
                            <i class="fa fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
                        </div>
                    </div>
                    <div class="sm:w-40">
                        <button id="search-btn" class="w-full bg-gray-100 hover:bg-gray-200 text-gray-700 py-2 px-4 rounded-md transition-colors">
                            搜索
                        </button>
                    </div>
                    <div class="sm:w-40">
                        <button id="refresh-btn" class="w-full bg-gray-100 hover:bg-gray-200 text-gray-700 py-2 px-4 rounded-md transition-colors">
                            <i class="fa fa-refresh mr-1"></i> 刷新
                        </button>
                    </div>
                </div>
            </div>
            
            <!-- 知识库列表 -->
            <div class="bg-white rounded-lg shadow-sm overflow-hidden">
                <div class="overflow-x-auto">
                    <table class="min-w-full divide-y divide-gray-200">
                        <thead class="bg-gray-50">
                            <tr>
                                <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                                    内容
                                </th>
                                <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                                    元数据
                                </th>
                                <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">
                                    操作
                                </th>
                            </tr>
                        </thead>
                        <tbody id="knowledge-table-body" class="bg-white divide-y divide-gray-200">
                            <!-- 知识库内容将通过JavaScript动态加载 -->
                            <tr>
                                <td colspan="3" class="px-6 py-10 text-center text-gray-500">
                                    <i class="fa fa-database text-4xl mb-2 opacity-30"></i>
                                    <p>加载知识库内容中...</p>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
                
                <!-- 分页 -->
                <div class="px-6 py-3 bg-gray-50 border-t border-gray-200 flex items-center justify-between">
                    <div class="text-sm text-gray-700">
                        显示 <span id="shown-count">0</span> 条，共 <span id="total-count">0</span> 条
                    </div>
                    <div class="flex space-x-2">
                        <button id="prev-page" class="px-3 py-1 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
                            上一页
                        </button>
                        <button id="next-page" class="px-3 py-1 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
                            下一页
                        </button>
                    </div>
                </div>
            </div>
        </main>
        
        <!-- 页脚 -->
        <footer class="bg-white border-t border-gray-200 py-4">
            <div class="max-w-7xl mx-auto px-4 text-center text-sm text-gray-500">
                RAG 知识库问答系统 &copy; 2025
            </div>
        </footer>
    </div>
    
    <!-- 添加/编辑知识模态框 -->
    <div id="knowledge-modal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden">
        <div class="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-[90vh] flex flex-col">
            <div class="px-6 py-4 border-b border-gray-200 flex items-center justify-between">
                <h3 id="modal-title" class="text-lg font-semibold text-gray-800">添加知识</h3>
                <button id="close-modal" class="text-gray-500 hover:text-gray-700">
                    <i class="fa fa-times text-xl"></i>
                </button>
            </div>
            
            <div class="px-6 py-4 flex-1 overflow-y-auto">
                <form id="knowledge-form">
                    <input type="hidden" id="knowledge-id">
                    
                    <div class="mb-4">
                        <label for="knowledge-content" class="block text-sm font-medium text-gray-700 mb-1">知识内容</label>
                        <textarea 
                            id="knowledge-content" 
                            rows="6" 
                            placeholder="输入要添加到知识库的内容..." 
                            class="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-primary focus:border-primary transition-all resize-none"
                            required
                        ></textarea>
                        <p class="mt-1 text-xs text-gray-500">请输入详细、准确的内容，这将有助于提高问答的准确性</p>
                    </div>
                    
                    <div class="mb-4">
                        <label for="knowledge-metadata" class="block text-sm font-medium text-gray-700 mb-1">元数据 (JSON格式)</label>
                        <textarea 
                            id="knowledge-metadata" 
                            rows="3"
                            class="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-primary focus:border-primary transition-all resize-none"
                        >{"type":"系统业务知识或规则/数据库表结构/数据字典/接口定义","title":"","related":""}</textarea>
                        <p class="mt-1 text-xs text-gray-500">可选，用于标识知识来源等附加信息，必须是有效的JSON格式，例如：{"source": "手册", "chapter": "第1章"}</p>
                    </div>
                </form>
            </div>
            
            <div class="px-6 py-4 border-t border-gray-200 flex justify-end space-x-3">
                <button id="cancel-btn" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors">
                    取消
                </button>
                <button id="save-btn" class="px-4 py-2 bg-primary hover:bg-primary/90 text-white rounded-md transition-colors">
                    保存
                </button>
            </div>
        </div>
    </div>
    
    <!-- 加载中模态框 -->
    <div id="loading-modal" class="fixed inset-0 bg-black/50 flex items-center justify-center z-50 hidden">
        <div class="bg-white p-6 rounded-lg flex items-center">
            <div class="animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-primary mr-4"></div>
            <p>正在处理您的请求...</p>
        </div>
    </div>

    <script>
        // 全局变量
        let currentPage = 1;
        const pageSize = 10;
        let totalItems = 0;
        let knowledgeItems = [];
        
        // DOM 元素
        const knowledgeTableBody = document.getElementById('knowledge-table-body');
        const addKnowledgeBtn = document.getElementById('add-knowledge-btn');
        const knowledgeModal = document.getElementById('knowledge-modal');
        const closeModalBtn = document.getElementById('close-modal');
        const cancelBtn = document.getElementById('cancel-btn');
        const saveBtn = document.getElementById('save-btn');
        const knowledgeForm = document.getElementById('knowledge-form');
        const knowledgeIdInput = document.getElementById('knowledge-id');
        const knowledgeContentInput = document.getElementById('knowledge-content');
        const knowledgeMetadataInput = document.getElementById('knowledge-metadata');
        const modalTitle = document.getElementById('modal-title');
        const searchInput = document.getElementById('search-input');
        const searchBtn = document.getElementById('search-btn');
        const refreshBtn = document.getElementById('refresh-btn');
        const prevPageBtn = document.getElementById('prev-page');
        const nextPageBtn = document.getElementById('next-page');
        const shownCountElement = document.getElementById('shown-count');
        const totalCountElement = document.getElementById('total-count');
        const loadingModal = document.getElementById('loading-modal');
        
        // 初始化
        document.addEventListener('DOMContentLoaded', () => {
            loadKnowledgeItems();
            
            // 事件监听
            addKnowledgeBtn.addEventListener('click', () => openModal());
            closeModalBtn.addEventListener('click', closeModal);
            cancelBtn.addEventListener('click', closeModal);
            saveBtn.addEventListener('click', saveKnowledgeItem);
            searchBtn.addEventListener('click', performSearch);
            refreshBtn.addEventListener('click', loadKnowledgeItems);
            prevPageBtn.addEventListener('click', goToPrevPage);
            nextPageBtn.addEventListener('click', goToNextPage);
            searchInput.addEventListener('keypress', (e) => {
                if (e.key === 'Enter') performSearch();
            });
        });
        
        // 加载知识库内容
        async function loadKnowledgeItems() {
            try {
                showLoading();
                currentPage = 1; // 重置到第一页
                
                const response = await fetch('/api/knowledge');
                if (!response.ok) throw new Error('加载知识库失败');
                
                knowledgeItems = await response.json();
                totalItems = knowledgeItems.length;
                
                renderKnowledgeTable();
                updatePagination();
            } catch (error) {
                console.error('加载知识库失败:', error);
                knowledgeTableBody.innerHTML = `
                    <tr>
                        <td colspan="3" class="px-6 py-10 text-center text-red-500">
                            <i class="fa fa-exclamation-circle mr-2"></i>
                            加载知识库失败，请刷新页面重试
                        </td>
                    </tr>
                `;
            } finally {
                hideLoading();
            }
        }
        
        // 渲染知识库表格
        function renderKnowledgeTable() {
            if (knowledgeItems.length === 0) {
                knowledgeTableBody.innerHTML = `
                    <tr>
                        <td colspan="3" class="px-6 py-10 text-center text-gray-500">
                            <i class="fa fa-file-text-o text-4xl mb-2 opacity-30"></i>
                            <p>知识库中暂无内容，请添加知识</p>
                        </td>
                    </tr>
                `;
                shownCountElement.textContent = '0';
                totalCountElement.textContent = '0';
                return;
            }
            
            // 分页处理
            const startIndex = (currentPage - 1) * pageSize;
            const endIndex = Math.min(startIndex + pageSize, knowledgeItems.length);
            const currentItems = knowledgeItems.slice(startIndex, endIndex);
            
            // 更新计数显示
            shownCountElement.textContent = currentItems.length;
            totalCountElement.textContent = totalItems;
            
            // 渲染表格内容
            knowledgeTableBody.innerHTML = '';
            currentItems.forEach(item => {
                const row = document.createElement('tr');
                row.className = 'hover:bg-gray-50 transition-colors';
                
                // 截断长内容以便显示
                const shortContent = item.content.length > 100 
                    ? item.content.substring(0, 100) + '...' 
                    : item.content;
                
                // 格式化元数据
                let metadataHtml = '无';
                if (item.metadata && Object.keys(item.metadata).length > 0) {
                    metadataHtml = Object.entries(item.metadata).map(([key, value]) => {
                        return `<div class="text-xs"><strong>${key}:</strong> ${value}</div>`;
                    }).join('');
                }
                
                row.innerHTML = `
                    <td class="px-6 py-4 whitespace-nowrap">
                        <div class="text-sm text-gray-900">${shortContent}</div>
                        <div class="text-xs text-gray-500 mt-1">ID: ${item.id}</div>
                    </td>
                    <td class="px-6 py-4">
                        <div class="text-sm text-gray-500">${metadataHtml}</div>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
                        <button class="text-primary hover:text-primary/80 mr-3 edit-btn" data-id="${item.id}">
                            <i class="fa fa-pencil"></i> 编辑
                        </button>
                        <button class="text-red-500 hover:text-red-600 delete-btn" data-id="${item.id}">
                            <i class="fa fa-trash"></i> 删除
                        </button>
                    </td>
                `;
                
                knowledgeTableBody.appendChild(row);
            });
            
            // 添加编辑和删除按钮的事件监听
            document.querySelectorAll('.edit-btn').forEach(btn => {
                btn.addEventListener('click', () => {
                    const id = btn.getAttribute('data-id');
                    editKnowledgeItem(id);
                });
            });
            
            document.querySelectorAll('.delete-btn').forEach(btn => {
                btn.addEventListener('click', () => {
                    const id = btn.getAttribute('data-id');
                    deleteKnowledgeItem(id);
                });
            });
        }
        
        // 更新分页控件
        function updatePagination() {
            const totalPages = Math.ceil(totalItems / pageSize);
            
            prevPageBtn.disabled = currentPage === 1;
            nextPageBtn.disabled = currentPage >= totalPages;
        }
        
        // 上一页
        function goToPrevPage() {
            if (currentPage > 1) {
                currentPage--;
                renderKnowledgeTable();
                updatePagination();
            }
        }
        
        // 下一页
        function goToNextPage() {
            const totalPages = Math.ceil(totalItems / pageSize);
            if (currentPage < totalPages) {
                currentPage++;
                renderKnowledgeTable();
                updatePagination();
            }
        }
        
        // 执行搜索
        function performSearch() {
            const searchTerm = searchInput.value.trim().toLowerCase();
            
            if (!searchTerm) {
                // 如果搜索词为空，显示所有内容
                loadKnowledgeItems();
                return;
            }
            
            // 过滤包含搜索词的项目
            const filteredItems = knowledgeItems.filter(item => 
                item.content.toLowerCase().includes(searchTerm) ||
                (item.metadata && Object.values(item.metadata).some(value => 
                    String(value).toLowerCase().includes(searchTerm)
                ))
            );
            
            // 更新显示
            currentPage = 1;
            knowledgeItems = filteredItems;
            totalItems = filteredItems.length;
            
            renderKnowledgeTable();
            updatePagination();
        }
        
        // 打开模态框
        function openModal() {
            // 重置表单
            knowledgeForm.reset();
            modalTitle.textContent = '添加知识';
            knowledgeIdInput.value = '';
            
            // 显示模态框
            knowledgeModal.classList.remove('hidden');
            knowledgeContentInput.focus();
        }
        
        // 关闭模态框
        function closeModal() {
            knowledgeModal.classList.add('hidden');
        }
        
        // 编辑知识项
        async function editKnowledgeItem(id) {
            try {
                showLoading();
                
                const response = await fetch(`/api/knowledge/${id}`);
                if (!response.ok) throw new Error('获取知识项失败');
                
                const item = await response.json();
                
                // 填充表单
                knowledgeIdInput.value = item.id;
                knowledgeContentInput.value = item.content;
                knowledgeMetadataInput.value = item.metadata ? JSON.stringify(item.metadata, null, 2) : '';
                modalTitle.textContent = '编辑知识';
                
                // 显示模态框
                knowledgeModal.classList.remove('hidden');
                knowledgeContentInput.focus();
            } catch (error) {
                console.error('编辑知识项失败:', error);
                showNotification('加载知识项失败', 'error');
            } finally {
                hideLoading();
            }
        }
        
        // 保存知识项（添加或更新）
        async function saveKnowledgeItem() {
            const id = knowledgeIdInput.value;
            const content = knowledgeContentInput.value.trim();
            let metadata = null;
            
            // 验证内容
            if (!content) {
                showNotification('知识内容不能为空', 'error');
                knowledgeContentInput.focus();
                return;
            }
            
            // 验证元数据（如果有）
            if (knowledgeMetadataInput.value.trim()) {
                try {
                    metadata = JSON.parse(knowledgeMetadataInput.value.trim());
                } catch (e) {
                    showNotification('元数据格式无效，请输入有效的JSON', 'error');
                    knowledgeMetadataInput.focus();
                    return;
                }
            }
            
            try {
                showLoading();
                
                const url = id ? `/api/knowledge` : `/api/knowledge`;
                const method = id ? 'POST' : 'POST'; // 对于更新和添加，我们都使用POST，ID存在则更新
                
                const response = await fetch(url, {
                    method: method,
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        id: id,
                        content: content,
                        metadata: metadata
                    })
                });
                
                if (!response.ok) throw new Error(id ? '更新知识失败' : '添加知识失败');
                
                // 关闭模态框并刷新列表
                closeModal();
                loadKnowledgeItems();
                
                showNotification(id ? '知识已更新' : '知识已添加', 'success');
            } catch (error) {
                console.error('保存知识项失败:', error);
                showNotification(id ? '更新知识失败' : '添加知识失败', 'error');
            } finally {
                hideLoading();
            }
        }
        
        // 删除知识项
        async function deleteKnowledgeItem(id) {
            if (!confirm('确定要删除这条知识吗？此操作不可恢复。')) {
                return;
            }
            
            try {
                showLoading();
                
                const response = await fetch(`/api/knowledge/${id}`, {
                    method: 'DELETE'
                });
                
                if (!response.ok) throw new Error('删除知识失败');
                
                // 刷新列表
                loadKnowledgeItems();
                showNotification('知识已删除', 'success');
            } catch (error) {
                console.error('删除知识项失败:', error);
                showNotification('删除知识失败', 'error');
            } finally {
                hideLoading();
            }
        }
        
        // 显示加载状态
        function showLoading() {
            loadingModal.classList.remove('hidden');
        }
        
        // 隐藏加载状态
        function hideLoading() {
            loadingModal.classList.add('hidden');
        }
        
        // 显示通知
        function showNotification(message, type = 'info') {
            // 创建通知元素
            const notification = document.createElement('div');
            notification.className = `fixed bottom-4 right-4 px-4 py-3 rounded-lg shadow-lg z-50 ${
                type === 'success' ? 'bg-green-500 text-white' : 
                type === 'error' ? 'bg-red-500 text-white' : 
                'bg-blue-500 text-white'
            } transform translate-y-20 opacity-0 transition-all duration-300`;
            notification.textContent = message;
            
            // 添加到页面
            document.body.appendChild(notification);
            
            // 显示通知
            setTimeout(() => {
                notification.classList.remove('translate-y-20', 'opacity-0');
            }, 10);
            
            // 3秒后隐藏通知
            setTimeout(() => {
                notification.classList.add('translate-y-20', 'opacity-0');
                setTimeout(() => {
                    document.body.removeChild(notification);
                }, 300);
            }, 3000);
        }
    </script>
</body>
</html>
